﻿// -----------------------------------------------------------
//
// ScreenManager.cs
//
// During Global Game Jam Metz - 28/01/2012
//
// -----------------------------------------------------------

using System;
using System.Diagnostics;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace GlobalGameJam
{
    public class ScreenManager : DrawableGameComponent
    {
        List<AGameScreen> screens = new List<AGameScreen>();
        List<AGameScreen> screensToUpdate = new List<AGameScreen>();
        InputState input = new InputState();
        SpriteBatch spriteBatch;
        SpriteFont font;
        Texture2D blankTexture;
        bool isInitialized;
        bool traceEnabled;

        public SpriteBatch SpriteBatch
        {
            get { return spriteBatch; }
        }

        public SpriteFont Font
        {
            get { return font; }
        }

        public bool TraceEnabled
        {
            get { return traceEnabled; }
            set { traceEnabled = value; }
        }

        public ScreenManager(Game game) : base(game)
        {

        }

        public override void Initialize()
        {
            base.Initialize();

            isInitialized = true;
        }

        protected override void LoadContent()
        {
            ContentManager content = Game.Content;

            spriteBatch = new SpriteBatch(GraphicsDevice);
            font = content.Load<SpriteFont>("SpriteFont1");
            blankTexture = content.Load<Texture2D>("blank");
            foreach (AGameScreen screen in screens)
            {
                screen.LoadContent();
            }
        }

        protected override void UnloadContent()
        {
            foreach (AGameScreen screen in screens)
            {
                screen.UnloadContent();
            }
        }

        public override void Update(GameTime gameTime)
        {
            input.Update();
            screensToUpdate.Clear();
            foreach (AGameScreen screen in screens)
                screensToUpdate.Add(screen);
            bool otherScreenHasFocus = !Game.IsActive;
            bool coveredByOtherScreen = false;
            while (screensToUpdate.Count > 0)
            {
                AGameScreen screen = screensToUpdate[screensToUpdate.Count - 1];
                screensToUpdate.RemoveAt(screensToUpdate.Count - 1);
                screen.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
                if (screen.ScreenState == ScreenState.TransitionOn || screen.ScreenState == ScreenState.Active)
                {
                    if (!otherScreenHasFocus)
                    {
                        screen.HandleInput(input);
                        otherScreenHasFocus = true;
                    }
                    if (!screen.IsPopup)
                        coveredByOtherScreen = true;
                }
            }
            if (traceEnabled)
                TraceScreens();
        }

        void TraceScreens()
        {
            List<string> screenNames = new List<string>();

            foreach (AGameScreen screen in screens)
                screenNames.Add(screen.GetType().Name);
            Debug.WriteLine(string.Join(", ", screenNames.ToArray()));
        }

        public override void Draw(GameTime gameTime)
        {
            foreach (AGameScreen screen in screens)
            {
                if (screen.ScreenState == ScreenState.Hidden)
                    continue;

                screen.Draw(gameTime);
            }
        }

        public void AddScreen(AGameScreen screen, PlayerIndex? controllingPlayer)
        {
            screen.ControllingPlayer = controllingPlayer;
            screen.ScreenManager = this;
            screen.IsExiting = false;
            if (isInitialized)
            {
                screen.LoadContent();
            }
            screens.Add(screen);
        }

        public void RemoveScreen(AGameScreen screen)
        {
            if (isInitialized)
            {
                screen.UnloadContent();
            }

            screens.Remove(screen);
            screensToUpdate.Remove(screen);
        }

        public void RemoveScreenByName(string name)
        {
            int i = 0;
            for (; i < screens.Capacity && screens[i].name != name; i++) ;
            Console.WriteLine(screens[i].name);
            RemoveScreen(screens[i]);
        }

        public AGameScreen[] GetScreens()
        {
            return screens.ToArray();
        }

        public void FadeBackBufferToBlack(float alpha)
        {
            Viewport viewport = GraphicsDevice.Viewport;

            spriteBatch.Begin();
            spriteBatch.Draw(blankTexture, new Rectangle(0, 0, viewport.Width, viewport.Height), Color.Black * alpha);
            spriteBatch.End();
        }
    }
}
